<?php 
namespace plugins\appmarket\controller;
use cmf\controller\PluginAdminBaseController;//引入此类
use think\Db;

/**
 * 生成整站模板控制器
 */
class CreateSiteTemplateController extends PluginAdminBaseController
{
	
	public function _initialize()
	{
		set_time_limit ( 0 ) ;
	}
	
	/**
	 * @adminMenu(
     *     'name'   => '生成整站模板',
     *     'parent' => 'AdminIndex/index',
     *     'display'=> true,
     *     'hasView'=> true,
     *     'order'  => 1000,
     *     'icon'   => '',
     *     'remark' => '生成整站模板',
     *     'param'  => ''
     * )
	 * 生成模板首页
	 */
	public function index()
	{
		//获取框架列表
		$frameworkList = $this->getFrameworkList();
		//获取模块列表
		$moduleList = $this->getModuleList();
		$tmp = [];
		foreach( $moduleList as $key => $value ) {
			$find = Db::name('module_template')->where( 'name' , $value [ 'name' ] )->where('status',3)->select();
			if( count($find) > 0  ){
				$tmp [] = $value ;
			}
		}
		$typeList = $this->getTypeList();
		
		$this->assign( 'typeList' , $typeList );
		$this->assign( 'frameworkList' , $frameworkList );
		$this->assign( 'moduleList' , $tmp );
		return $this->fetch( 'create_site_template/index' );
	}
	
	//获取分类
	private function getTypeList()
	{
		$list = Db::name( 'module_template_classify' )->select()->toArray();
		return $list ;
	}

	/**
	 * 获取框架列表
	 * cmf_module_temp_framework
	 */
	private function getFrameworkList()
	{
		$frameworkList = Db::name( 'module_temp_framework' )->field('id,name,describe')->select()->toArray();
		return $frameworkList;
	}

	/**
	 * 获取所有模块列表
	 */
	private function getModuleList()
	{
		$moduleList = Db::name( 'module_store' )->field( 'id,name,title' )->order('CONVERT(title USING gbk)')->group('name')->select()->toArray();
		//$str = 'select id,name,title from `module_store` order by title using gbk ,group by name';
		//$moduleList = Db::query($str);
		return $moduleList;
	}

	/**
	 * 获取模板列表
	 */
	public function getTemplateList ()
	{
		$param = $this->request->param();
		$moduleSymbol = $param [ 'moduleSymbol' ];
		$moduleTemplateList = Db::name('module_template')->where( 'name' , $moduleSymbol )->where('status',3)->field('id,template_name,module_store_id,name,title,version,introduce,warning,type')->order('version')->select()->toArray();
		if( empty($moduleTemplateList) ){
			return zy_json_echo( false , '未获取到记录!' );
		}
		return zy_json_echo( true , '' , $moduleTemplateList );
	}

	/**
	 * 保存数据
	 * 创建整站记录表 cmf_module_site_template_records
	 */
	public function createSiteTemplate()
	{
		$param = $this->request->param();
		$param = $param [ 'data' ] ;
		$insert [ 'framework_id' ]  = $param [ 'selectFramework' ] ;	
		$insert [ 'template_ids'] = implode( ',' , $param['selectTemplateList'] );
		$insert [ 'type' ] = implode(',',$param['selectType']);
		$insert [ 'domain_name' ] = $param [ 'domainName' ] ;
		$insert [ 'add_time' ]  = time(); 
		$insert [ 'name' ] = $param[ 'webName' ];
		$insert [ 'remarks' ] = $param [ 'remarks' ];
		$insert [ 'user_id' ]  = cmf_get_current_admin_id();
		$insert [ 'user_name' ] = Db::name('user')->where( 'id' , $insert [ 'user_id' ] )->value( 'user_login' );

		$res = Db::name( 'module_site_template_records' )->insertGetId( $insert );
		if( $res > 0 ){
			//操作步骤  1.保存创建信息 返回状态; 2.前台再次请求执行压缩操作
			return zy_json_echo( true , '创建信息保存成功,正在打包文件,请勿操作...' , $res );
		}
		return zy_json_echo( false , '创建失败,请稍后再试!' );
	}

	/**
	 *合并文件
	 *整站模板资源文件保存路径 /upload/webSiteTemplate/records_id
	 */
	public function mergeFile( )
	{
		$rootPath = ROOT_PATH.'public';
		$param = $this->request->param();
		$recordsId = $param [ 'recordsId' ] ;

		$framework = Db::name( 'module_site_template_records' )->where( 'id' , $recordsId )->find();
		//获取框架文件路径
		$frameworkPath = Db::name( 'module_temp_framework' )->where( 'id' , $framework [ 'framework_id' ] )->value( 'src' );
		//exit;
		//移动框架文件
		$targetPath = $rootPath.DS.'upload'.DS.'webSiteTemplate'.DS.$recordsId;
		//dump($targetPath);exit;
		if( !file_exists( $targetPath ) ){
			mkdir( $targetPath );
			chmod( $targetPath , 0777 );
		}
		$frameworkPath = $rootPath.DS.$frameworkPath;

		$baseName = basename( $frameworkPath );

		$res = $this->copyFile(  $frameworkPath , $targetPath.DS.$baseName );
		if( $res == false ){
			return zy_json_echo( false , '复制框架文件失败,请稍后再试!' );
		}	
		//解压文件
		$res = $this->uzip( $targetPath , $targetPath.DS.$baseName );
		if( $res != true ){
			return zy_json_echo( false , '解压框架文件失败,请稍后再试!' );
		}
		//解压完成后删除.zip框架源文件
		unlink( $targetPath.DS.$baseName );
		
		//创建基础文件
		$content = ["baseUrl"=>$framework['domain_name']];
		$createHttpJsonFilePath = $targetPath.DS.'http.json';
		try{
			file_put_contents( $createHttpJsonFilePath , json_encode($content,JSON_UNESCAPED_UNICODE) , true );
		}catch( \Exception $e ){
			return zy_json_echo( false , $e->getMessage());
		}
		

		//获取模板文件路径
		$templatePaths = [];
		$templateIds = explode( ',', $framework [ 'template_ids' ]  ); 
		$templateList = Db::name( 'module_template' )->where( 'id' , 'IN' , $templateIds  )->select()->toArray();


		//框架模块目录
		$fwModulePath = $targetPath.DS.'src'.DS.'components';
		if( !file_exists( $fwModulePath ) ){
			return zy_json_echo( false , '框架目录读取错误,无法执行模块复制!错误路径：'.$fwModulePath );
		}

		foreach ( $templateList as $key => $value ) {
			//移动文件
			try {
				$type = $value['type'];
				$moduelBaseName = basename( $value[ 'resource' ] );
				$moduleSourcePath = $rootPath.DS.$value [ 'resource' ] ;
				
				$copyTargetPath = $fwModulePath.DS.$type;
				
				if( !file_exists( $copyTargetPath ) ){
					mkdir( $copyTargetPath , 0777 , true );
				}
				
				$res = $this->copyFile( $moduleSourcePath , $copyTargetPath.DS.$moduelBaseName );
				if( $res == false ){
					return zy_json_echo( false , '复制模板文件失败,请稍后再试!' );
				}	
				
				//解压文件
				$res = $this->uzip( $copyTargetPath ,  $copyTargetPath.DS.$moduelBaseName );
				if( $res != true ){
					return zy_json_echo( false , '解压模板文件失败,请稍后再试!' );
				}
				//解压完成后删除模板源文件
				unlink( $copyTargetPath.DS.$moduelBaseName  );

			} catch ( \Exception $e ) {

				return zy_json_echo( false , '复制模板文件异常:'.$e->getMessage() );
			}	
		}
		return zy_json_echo( true, '文件合并成功,正在进行压缩,请稍后...' , $recordsId );
	}

	//执行压缩
	public function compression( $recordsId )
	{
		//压缩整站文件包
		$rootPath = ROOT_PATH.'public';
		$path = $rootPath.DS.'upload'.DS.'webSiteTemplate'.DS.$recordsId;
		$framework = Db::name( 'module_site_template_records' )->where( 'id' , $recordsId )->find();

		$targetPath = $rootPath.DS.'upload'.DS.'webSiteTemplate'.DS.$recordsId;
		$zipName = $targetPath.DS.'..'.DS.$recordsId.'.zip';
		$zipName = iconv( 'GBK' , 'utf-8' , $zipName);

		$fileName = '/upload'.DS.'webSiteTemplate'.DS.$recordsId.'.zip';


		$zip=new \ZipArchive();
		try {
			if($zip->open( $zipName , \ZipArchive::OVERWRITE)=== TRUE){
			    if(is_dir($path)){  //给出文件夹，打包文件夹
			        $this->addFileToZip($path, $zip);
			    }else{      //只给出一个文件
			        $zip->addFile($path);
			        $zip->renameName($path);
			    }
			    $zip->close(); //关闭处理的zip文件
			    Db::name('module_site_template_records')->where( 'id' , $recordsId )->update( [ 'src' => $fileName ] );
			    return zy_json_echo( true , '导出成功!' , cmf_plugin_url('Appmarket://CreateSiteTemplate/recordList') );
			}else{
				return  zy_json_echo(  false ,  '文件压缩失败!' );
			}
		} catch (\Exception $e) {
			return  zy_json_echo( false , '异常:'.$e->getMessage() );
		}
	}

	/**
	 * 复制文件到制定目录文件
	 */
	private function copyFile( $sourcePath , $targetPath )
	{
		copy( $sourcePath, $targetPath );
		return true;
	}


	/**
     * 解压文件
     */
    private function uzip( $outPath = '' , $fileName = '' )
    {
        $res = true;
        $zip = new \ZipArchive();
        try {
            $openRes = $zip->open( $fileName );
            if ($openRes === TRUE) {
              $zip->extractTo($outPath);
              $zip->close();
            }
        } catch (\Exception $e) {
            $res = [ 'status' => false , 'message' => '异常:'.$e->getMessage() ];
        }
        return $res;
    }

    /**
     * 压缩文件
     */
    private function addFileToZip( $path , $zip , $subDir = '')
    {
	    $handler = opendir($path); //打开当前文件夹由$path指定。
	    $isEmpty = true;
	    while( ($filename=readdir($handler))!==false ){
	        if($filename != "." && $filename != ".."){//文件夹文件名字为'.'和‘..’，不要对他们进行操作
	            if( is_dir($path.'/'.$filename) ){// 如果读取的某个对象是文件夹，则递归
	                $this->addFileToZip($path.'/'.$filename, $zip , $subDir.$filename.'/');
	            }else{ //将文件加入zip对象
	                $zip->addFile($path."/".$filename);
	                $zip->renameName($path."/".$filename,$subDir.$filename);
	            }
	            $isEmpty = false;
	        }
	    }
	    if( $isEmpty ){
	    	//添加空目录
			$zip->addEmptyDir($subDir);
	    }
	    @closedir($path);
	}
	
	//循环删除目录和文件函数
	private function delDirAndFile( $dirName ) 
	{ 
		if ( $handle = opendir( "$dirName" ) ) { 
			while ( false !== ( $item = readdir( $handle ) ) ) { 
				if ( $item != "." && $item != ".." ) { 
					if ( is_dir( "$dirName/$item" ) ) { 
						delDirAndFile( "$dirName/$item" ); 
					} else { 
						if( unlink( "$dirName/$item" ) );
					} 
				} 
			} 
			closedir( $handle ); 
			if( rmdir( $dirName ) ) return true; 
		} 
	}
	
	
	/**
	 * 框架生成历史表
	 * @adminMenu(
     *     'name'   => '框架导出记录',
     *     'parent' => 'index',
     *     'display'=> true,
     *     'hasView'=> true,
     *     'order'  => 1000,
     *     'icon'   => '',
     *     'remark' => '框架生成记录',
     *     'param'  => ''
     * )
	 */
	public function recordList()
	{
		$list  = Db::name( 'module_site_template_records' )->order('add_time DESC')->paginate(20);
		$this->assign( 'list' , $list );
		return $this->fetch( 'create_site_template/record_list' );
	}
	
	/**
	 * 框架导出记录删除
	 * @adminMenu(
     *     'name'   => '框架导出记录删除',
     *     'parent' => 'index',
     *     'display'=> false,
     *     'hasView'=> false,
     *     'order'  => 1000,
     *     'icon'   => '',
     *     'remark' => '框架导出记录删除',
     *     'param'  => ''
     * )
	 */
	public function recordDel()
	{
		$param = $this->request->param();
		$id = $param [ 'id' ];
		$record = Db::name( 'module_site_template_records' )->where( 'id' , $id )->find();
		$path = APP_PATH.DS.'..'.DS.'public'.DS.$record['src'];
		if( !empty( $record['src'] ) ) 
		{
			$path = iconv("UTF-8","GBK",$path);
			if( file_exists($path) ) unlink( $path );
		}
		
		$res = Db::name( 'module_site_template_records' )->where( 'id' , $id )->delete();
		if( !$res ){
			//$this->error('删除记录失败!');
			return zy_json_echo(false, '删除记录失败!' );
		}
		//$this->success( '删除记录成功!' );
		return zy_json_echo( true , '删除记录成功!' );
	}
    




}